package com.atguigu.spring6.aop.annoaop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

// 切面类
@Aspect //切面类
@Component //ioc容器中管理
public class LogAspect {
    //设置切入点和通知类型
    //切入点表达式：
    // execution(访问权限符 返回值类型 方法所在类全路径.方法名(参数列表))
    //通知类型：
    // 前置通知:@Before(value="切入点表达式配置切入点")
    //@Before("execution(* com.atguigu.spring6.aop.annoaop.CalculatorImpl.*(..))")
    @Before("execution(public int com.atguigu.spring6.aop.annoaop.CalculatorImpl.*(..))")
    public void beforeMethod() {
        System.out.println("Logger-->前置通知");
    }
    // 返回:@AfterReturning()
   @AfterReturning(value = "execution(* com.atguigu.spring6.aop.annoaop.CalculatorImpl.add(..))",returning = "result")
    public void afterReturningMethod(JoinPoint joinPoint,Object result) {
        String methonName=joinPoint.getSignature().getName();
        System.out.println("Logger-->返回通知，结果是："+result);

    }
    // 异常:@AfterThrowing()
    //目标方法出现异常，这个通知执行
     @AfterThrowing(value = "execution(* com.atguigu.spring6.aop.annoaop.CalculatorImpl.sub(..))",throwing = "ex")
    public void afterThrowingMethod(JoinPoint joinPoint,Throwable ex) {
        String methonName=joinPoint.getSignature().getName();
        Object[] args=joinPoint.getArgs();
        System.out.println("Logger->异常通知，方法名称："+methonName+",异常信息："+ex);
    }
    // 后置:@After()
    @After(value = "pointCut()") //重用切入表达式
    public void afterMethod(JoinPoint joinPoint) {
        String methonName=joinPoint.getSignature().getName();
        Object[] args=joinPoint.getArgs();
        System.out.println("Logger-->后置通知,方法名称："+methonName+"，参数："+ Arrays.toString(args));
    }
    // 环绕:@Around()
    @Around(value = "execution(* com.atguigu.spring6.aop.annoaop.CalculatorImpl.sub(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) {
        String methonName=joinPoint.getSignature().getName();
        Object[] args=joinPoint.getArgs();
        System.out.println("Logger-->后置通知,方法名称："+methonName+"，参数："+ Arrays.toString(args));
        Object result=null;
        try {
            //前置通知
            System.out.println("环绕通知-->目标执行之前执行");
            //目标方法执行
            result=joinPoint.proceed();
            //返回通知
            System.out.println("环绕通知-->返回通知");
        }catch (Throwable e){
            //异常通知
            System.out.println("环绕通知-->异常通知");
        }
        //后置通知
        System.out.println("环绕通知-->后置通知");
        return result;
    }
    //重用切入点表达式
    @Pointcut("execution(* com.atguigu.spring6.aop.annoaop.CalculatorImpl.*(..))")
    public void pointCut() {

    }
}
